﻿import { h, type VNode } from 'vue';
import i18n from '@/lang/index';
import SvgIcon from '@/components/common/svgicon/index.vue';

function tips(message: string, type: string, svg: any) {
    ElMessage({
        message,
        type,
        dangerouslyUseHTMLString: true,
        customClass: 'mes-ElMessage',
        offset: 100,
        icon: svg,
        grouping: true,
        // duration: 0,
    });
}

export const errorTips = (message: string) => {
    tips(
        message,
        'error',
        h(SvgIcon, {
            name: 'error',
            color: '#E34D59',
        })
    );
};

export const successTips = (message: string) => {
    tips(
        message,
        'success',
        h(SvgIcon, {
            name: 'success',
            color: '#62B574',
        })
    );
};

export const warningTips = (message: string) => {
    tips(
        message,
        'warning',
        h(SvgIcon, {
            name: 'warning',
            color: '#E77E00',
        })
    );
};

/* 文件地址下载 */
export const locationDownLoad = (url: string) => {
    if (!url) {
        errorTips('无下载地址');
        return false;
    }
    const link = document.createElement('a');
    link.href = url;
    link.click();
    document.body.appendChild(link);
};

/**
 * 存储sessionStorage
 */
export const setStore = (name: string, content: any) => {
    if (!name) return;
    if (typeof content !== 'string') {
        content = JSON.stringify(content);
    }
    window.sessionStorage.setItem(name, content);
};

/**
 * 获取sessionStorage
 */
export const getStore = (name: string) => {
    if (!name) return;
    let content = window.sessionStorage.getItem(name);
    if (!content) return '';
    if (content.indexOf('{') >= 0 || content.indexOf('[') >= 0) {
        return JSON.parse(content);
    } else {
        return content;
    }
};

/**
 * 删除sessionStorage
 */
export const removeStore = (name: string) => {
    if (!name) return;
    window.sessionStorage.removeItem(name);
};

/**
 * 将Base64图片转换为File对象
 * @param {String} base64 - 带前缀的Base64字符串
 * @param {String} [filename='image'] - 生成的文件名
 * @param {String} [mimeType='image/png'] - 文件类型
 * @returns {Promise<File>}
 */
export function base64ToFile(base64: string, filename = 'image', mimeType = 'image/png') {
    // 1. 移除Base64前缀（如果存在）
    const base64Data = base64.split(',')[1] || base64;

    // 2. 转换为二进制字符串
    const binaryStr = atob(base64Data);

    // 3. 转换为Uint8Array
    const length = binaryStr.length;
    const uint8Array = new Uint8Array(length);
    for (let i = 0; i < length; i++) {
        uint8Array[i] = binaryStr.charCodeAt(i);
    }

    // 4. 创建File对象
    return new File([uint8Array], `${filename}.${mimeType.split('/')[1]}`, {
        type: mimeType,
    });
}

/**
 * 时间戳格式化
 */
export const getDateTime = function (timestamp?: string) {
    let t = null;
    // 不传值，则获取当前时间
    if (timestamp === undefined) {
        t = new Date();
    } else if (timestamp) {
        t = new Date(parseInt(timestamp));
    }

    if (t) {
        let n: string = t.getFullYear() + '';
        let a: string = t.getMonth() + 1 + '';
        let r: string = t.getDate() + '';
        let o: string = t.getHours() + '';
        let i: string = t.getMinutes() + '';
        let s: string = t.getSeconds() + '';

        parseInt(a) >= 10 || (a = '0' + a),
            parseInt(r) >= 10 || (r = '0' + r),
            parseInt(o) >= 10 || (o = '0' + o),
            parseInt(i) >= 10 || (i = '0' + i),
            parseInt(s) >= 10 || (s = '0' + s);

        return [
            n, // yy 0
            a, // mm 1
            r, // dd 2
            n + '-' + a, // yy-mm 3
            a + '/' + r, // mm/dd 4
            o + ':' + i + ':' + s, // hh:mm:ss 5
            n + '-' + a + '-' + r + ' ' + o + ':' + i + ':' + s, // yy-mm-dd hh:mm::ss 6
            a + '-' + r + ' ' + o + ':' + i + ':' + s, // mm-dd hh:mm::ss 7
            n + '-' + a + '-' + r, // yy-mm-dd 8
            n + a + r, // yymmdd 9
            n + a, //yymm 10
            n + '-' + a + '-' + r + ' ' + o + ':' + i, // yy-mm-dd hh:mm 11
        ];
    } else {
        return ['--', '--', '--', '--', '--', '--', '--', '--', '--'];
    }
};

/**
 * 日期转时间戳
 */
export const getTimestamp = (e: string) => {
    var t;
    if (e) {
        e = e.replace(/-/g, '/');
        t = new Date(e);
    } else t = new Date();
    return t.getTime().toString();
};

// 邮箱校验
export function validateEmail(email: string) {
    const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    return regex.test(email);
}

// 判断当前环境
export function detectDevice() {
    const userAgent = navigator.userAgent.toLowerCase();
    if (/android/.test(userAgent)) {
        return 'android';
    } else if (/iphone|ipad|ipod/.test(userAgent)) {
        return 'ios';
    } else {
        return 'pc';
    }
}

/**
 * Base64加密，去除特殊字符，防止浏览器默认解析
 * @param text
 * @returns
 */

export const encryptBase64 = (text: string) => {
    // 1. 使用encodeURIComponent处理特殊字符
    const encodedText = encodeURIComponent(text);
    // 2. 使用btoa进行Base64编码
    const base64Encoded = btoa(encodedText);
    // 3. 将Base64中的'+', '/'替换为英文字符，处理'='
    return base64Encoded
        .replace(/\+/g, '-') // '+' 替换为 '-'
        .replace(/\//g, '_') // '/' 替换为 '_'
        .replace(/=+$/, ''); // 移除末尾的 '='
};

/**
 * Base64解密
 * @returns
 */
export const decryptBase64 = (encryptedText: string) => {
    // 1. 还原Base64编码中的特殊字符
    let base64Encoded = encryptedText
        .replace(/-/g, '+') // '-' 还原为 '+'
        .replace(/_/g, '/'); // '_' 还原为 '/'

    // 2. 添加被移除的 '='
    while (base64Encoded.length % 4 !== 0) {
        base64Encoded += '=';
    }

    // 3. 使用atob进行Base64解码
    const decodedText = atob(base64Encoded);
    // 4. 使用decodeURIComponent还原原始字符串
    return decodeURIComponent(decodedText);
};

export const isLoginFun = () => {
    let token = getStore('esign_token');
    return token ? true : false;
};

/**
 * 图片转base64
 *
 * @param url
 * @returns
 */
export const imgToBase64 = async (url: string) => {
    return new Promise(async (reslove, reject) => {
        try {
            // 1. 使用 fetch 获取图片二进制数据
            const response = await fetch(url);
            const blob = await response.blob();

            // 2. 使用 FileReader 转换为 Base64
            const reader = new FileReader();
            reader.onloadend = () => {
                reslove(reader.result as string);
            };
            reader.readAsDataURL(blob);
        } catch (error) {
            reject(error);
        }
    });
};

/**
 * 去抖动函数
 */
export const debounce = <T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    immediate = false
): ((...args: Parameters<T>) => ReturnType<T> | undefined) => {
    let timeout: ReturnType<typeof setTimeout> | null = null;

    return function (this: any, ...args: Parameters<T>): ReturnType<T> | undefined {
        const context = this;
        const later = () => {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };

        const callNow = immediate && !timeout;

        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(later, wait);

        if (callNow) return func.apply(context, args);
    };
};

// 节流
export const throttle = <T extends (...args: any[]) => any>(
    func: T,
    limit: number
): ((...args: Parameters<T>) => ReturnType<T> | undefined) => {
    let lastFunc: ReturnType<typeof setTimeout> | null = null;
    let lastRan: number | null = null;

    return function (this: any, ...args: Parameters<T>): ReturnType<T> | any {
        const context = this;

        if (!lastRan) {
            func.apply(context, args);
            lastRan = Date.now();
        } else {
            if (lastFunc) clearTimeout(lastFunc);

            lastFunc = setTimeout(() => {
                if (Date.now() - lastRan! >= limit) {
                    func.apply(context, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan!)) as ReturnType<typeof setTimeout>;
        }
    };
};

/**
 * 现代化的复制功能 - 使用 Clipboard API
 * @param val 需要复制的文本内容
 */
export const onCopy = async (val: any) => {
    try {
        // 优先使用现代 Clipboard API
        if (navigator.clipboard && window.isSecureContext) {
            // 使用 Clipboard API (需要 HTTPS 环境)
            await navigator.clipboard.writeText(val);
            successTips(i18n.global.t('Setting.CopySuccessful'));
        } else {
            // 降级到传统方法
            fallbackCopyTextToClipboard(val);
        }
    } catch (err) {
        console.error('复制失败:', err);
        // 如果现代方法失败，尝试降级
        try {
            fallbackCopyTextToClipboard(val);
        } catch (fallbackErr) {
            console.error('降级复制也失败了:', fallbackErr);
            errorTips(i18n.global.t('Setting.CopyFailed'));
        }
    }
};

/**
 * 传统的复制方法 - 作为降级方案
 * @param text 需要复制的文本
 */
function fallbackCopyTextToClipboard(text: string) {
    const textArea = document.createElement('textarea');
    textArea.value = text;

    // 避免滚动到底部
    textArea.style.top = '0';
    textArea.style.left = '0';
    textArea.style.position = 'fixed';
    textArea.style.opacity = '0';

    document.body.appendChild(textArea);
    textArea.focus();
    textArea.select();

    try {
        const successful = document.execCommand('copy');
        if (successful) {
            successTips(i18n.global.t('Setting.CopySuccessful'));
        } else {
            errorTips(i18n.global.t('Setting.CopyFailed'));
        }
    } catch (err) {
        throw new Error('传统复制方法失败');
    } finally {
        document.body.removeChild(textArea);
    }
}
/**
 * 获取浏览器URL中的查询参数
 * @param url 可选，要解析的URL，默认为当前页面URL
 * @returns 返回解析后的查询参数对象
 */
export function getUrlParams(url?: string): Record<string, string> {
    const targetUrl = url || window.location.href;
    const params: Record<string, string> = {};

    // 处理标准URL参数（如：http://example.com?a=1&b=2）
    const standardQueryIndex = targetUrl.indexOf('?');
    if (standardQueryIndex !== -1) {
        const queryString = targetUrl.slice(standardQueryIndex + 1);
        const hashIndex = queryString.indexOf('#');
        const cleanQuery = hashIndex !== -1 ? queryString.slice(0, hashIndex) : queryString;

        cleanQuery.split('&').forEach(param => {
            if (param) {
                const [key, value] = param.split('=');
                if (key) {
                    params[key] = value ? encodeURIComponent(value) : '';
                }
            }
        });
    }

    // 处理哈希路由中的参数（如：http://example.com/#/page?a=1&b=2）
    const hashIndex = targetUrl.indexOf('#');
    if (hashIndex !== -1) {
        const hashPart = targetUrl.slice(hashIndex + 1);
        const hashQueryIndex = hashPart.indexOf('?');

        if (hashQueryIndex !== -1) {
            const hashQueryString = hashPart.slice(hashQueryIndex + 1);

            hashQueryString.split('&').forEach(param => {
                if (param) {
                    const [key, value] = param.split('=');
                    if (key) {
                        // 优先使用哈希中的参数（覆盖标准URL中的同名参数）
                        params[key] = value ? encodeURIComponent(value) : '';
                    }
                }
            });
        }
    }

    return params;
}

/**
 * pdf下载
 * @param res 流
 * @param name 名称
 * @param mimeType
 * @returns
 */
export const BlobDownLoad = (res: any, name: string, mimeType = 'application/pdf') => {
    // 检测浏览器类型
    const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
    const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    const isChrome = /CriOS/i.test(navigator.userAgent);

    try {
        const blob = new Blob([res.data], { type: mimeType });

        // iOS Safari特殊处理
        if (isIOS && isSafari) {
            // iOS Chrome特殊处理
            if (isChrome) {
                warningTips('请在safari浏览器中下载');
                return;
            }

            // 创建iframe
            const iframe = document.createElement('iframe');
            iframe.style.display = 'none';
            document.body.appendChild(iframe);

            const url = URL.createObjectURL(blob);

            // 在iframe中打开URL
            const iframeDoc: any = iframe.contentDocument || iframe.contentWindow?.document;
            iframeDoc.open();
            iframeDoc.write(
                `<html><body><a href="${url}" download="${name}" id="downloadLink" style="display:block;">下载</a><script>document.getElementById('downloadLink').click();</script></body></html>`
            );
            iframeDoc.close();
            return;
        }

        // 其他浏览器标准下载流程
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = name;

        document.body.appendChild(link);
        link.click();

        setTimeout(() => {
            document.body.removeChild(link);
            URL.revokeObjectURL(url);
        }, 100);
    } catch (error) {
        console.error('下载失败:', error);
        alert('下载失败，请尝试在浏览器中打开文件');
    }
};

/**
 * 手机号脱敏处理
 * 格式：保留区号和手机号前3位、后四位，中间用4个“*”
 * @param phoneNumber 手机号字符串，支持带区号的格式，如 "+8613800138000" 或 "86 13800138000"
 * @returns 脱敏后的手机号字符串
 */
export class PrivacyMasker {
    static maskPhoneNumber(phoneNumber: string): string {
        if (!phoneNumber) return '';

        // 提取区号（如果有）
        let areaCode = '';
        let phoneNum = phoneNumber.trim();

        // 处理带区号的情况
        const areaCodeMatch = phoneNum.match(/^(\+\d{1,3}|\d{1,3})[\s-]?/);
        if (areaCodeMatch) {
            areaCode = areaCodeMatch[1] as string;
            phoneNum = phoneNum.replace(areaCodeMatch[0], '').trim();
        }

        // 处理手机号主体部分
        if (phoneNum.length <= 7) {
            // 太短的号码不处理
            return phoneNumber;
        }

        // 保留前3位和后4位，中间用*替换
        const maskedPart = phoneNum.substring(3, phoneNum.length - 4).replace(/./g, '*');
        const maskedPhone = phoneNum.substring(0, 3) + maskedPart + phoneNum.substring(phoneNum.length - 4);

        // 重新组合区号和手机号
        return areaCode ? `${areaCode} ${maskedPhone}` : maskedPhone;
    }

    /**
     * 邮箱脱敏处理
     * 格式：保留前三位、后三位，中间用4个“*”
     * @param email 邮箱字符串
     * @returns 脱敏后的邮箱字符串
     */
    static maskEmail(email: string): string {
        if (!email) return '';

        const [localPart, domain] = email.split('@');
        if (!localPart || !domain) return email;

        if (localPart.length <= 6) {
            // 太短的用户名只保留第一位和4个*
            return localPart[0] + '****' + '@' + domain;
        }

        // 保留前3位和后3位，中间用*替换
        const maskedLocalPart = localPart.substring(0, 3) + '****' + localPart.substring(localPart.length - 3);

        return `${maskedLocalPart}@${domain}`;
    }
}

/**
 * 简单的十六进制转 RGB 函数（不支持简写形式如 #FFF）
 */

export const getBgStyle = (hexColor: string) => {
    const hex = hexColor.replace('#', '');
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);

    return `rgba(${r}, ${g}, ${b}, 0.3)`;
};

/**
 *设置打开的屏幕大小 window.open()
 * widthPercent 80 80%
 * heightPercent 80 80%
 */

export const openSizedWindow = (widthPercent: number, heightPercent: number) => {
    const screenW = window.screen.width;
    const screenH = window.screen.height;
    const w = Math.round((screenW * widthPercent) / 100);
    const h = Math.round((screenH * heightPercent) / 100);
    const left = (screenW - w) / 2; // 居中显示
    const top = (screenH - h) / 2;
    return `width=${w},height=${h},left=${left},top=${top}`;
};

// 卸载全局 loading
export const unmountGlobalLoading = () => {
    const loadingElement = document.querySelector('#__app-loading__');

    if (loadingElement) {
        // 添加隐藏类，触发过渡动画
        loadingElement.classList.add('hidden');

        // 查找所有需要移除的注入 loading 元素
        const injectLoadingElements = document.querySelectorAll('[data-app-loading^="inject"]');

        // 当过渡动画结束时，移除 loading 元素和所有注入的 loading 元素
        loadingElement.addEventListener(
            'transitionend',
            () => {
                loadingElement.remove(); // 移除 loading 元素
                injectLoadingElements.forEach(el => el.remove()); // 移除所有注入的 loading 元素
            },
            { once: true }
        ); // 确保事件只触发一次
    }
};
